Skip to content

feat(worktrees): manage lifecycle on orchestrator v2 - #5589

Open
StiensWout wants to merge 389 commits into
pingdotgg:t3code/codex-turn-mappingfrom
StiensWout:t3code/worktree-management-v2
Open

feat(worktrees): manage lifecycle on orchestrator v2#5589
StiensWout wants to merge 389 commits into
pingdotgg:t3code/codex-turn-mappingfrom
StiensWout:t3code/worktree-management-v2

Conversation

@StiensWout

@StiensWout StiensWout commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Important

Stacked pull request. This targets t3code/codex-turn-mapping from #2829. After #2829 merges, rebase this branch and retarget the PR to main.

Problem

Thread worktrees accumulate without a server-owned way to inspect or clean them. The previous cleanup prompt only worked in the desktop client, and a removed worktree could strand the next provider turn.

Solution

  • Derive a per-environment inventory from Git and V2 thread projections.
  • Protect worktrees with active threads, local changes, unpushed commits, or unavailable status. Revalidate immediately before non-forced removal.
  • Apply configurable retention and optional immediate cleanup after the last linked thread is deleted.
  • Recreate a missing worktree from its retained branch before provider startup, then restart a per-thread provider session when its working directory changes. An existing worktree is never touched, whatever it has checked out and wherever it lives; sessions shared across threads (Codex) stay open.
  • Add a project-grouped Worktrees inventory to Settings → Source Control for every compatible connected environment: one line per worktree (branch, linked thread, last use, sync state, and either Remove or the blockers), two plain settings rows for the cleanup policy, and rows that disappear as soon as removal is confirmed.
  • Treat a detached worktree like a branch without an upstream: safe once its commit is on the default branch, otherwise blocked as unmerged. Previously it was marked status-unavailable forever.
  • Read the inventory with one git status per worktree, concurrently with the ahead-of-default count, and fetch the per-repository listing, branch sync, and default ref together. On a 2-vCPU environment with 8 worktrees the inventory went from 5.0 s to 0.6 s. Mounting the section no longer issues a duplicate read.
  • Keep local branches and checkpoint refs so cleanup remains reversible through automatic revival.

The refresh also removes the unused public revive RPC, fixes provider-start supersession after a mandatory session reopen, parses git worktree list --porcelain -z everywhere (main already requires -z in listRefs), keeps the reaper behind the activation boundary, lets interrupts stop sweeps and status reads, and skips projects outside a Git repository instead of failing the inventory.

Safety

  • All worktree mutations share one server-side permit.
  • Inventory combines projects that share a Git common directory, including nested project roots.
  • Paths are canonicalized, and revival rejects symlink-ancestor escapes outside the managed worktree root.
  • Automatic and manual cleanup never force-removes a worktree or deletes its branch.

Screenshots

Light Dark
Worktree settings, light Worktree settings, dark

Verification

  • Targeted typechecks pass for server, contracts, client runtime, and web.
  • Targeted lint, formatting, and diff checks pass.
  • The isolated worktree dev environment starts and serves the app successfully.
  • Added tests were reduced by 669 lines, keeping focused Git, lifecycle, cleanup, revival, and destructive-safety coverage. Later rounds add coverage for detached worktrees, mixed repository and plain-directory projects, and NUL-terminated worktree listings.

Initial implementation and the refresh were produced with GPT-5.6 Sol via Codex in T3 Code. The one-line settings layout, detached-HEAD handling, inventory speed-up, and review follow-ups were done by Claude Fable 5 via Claude Code in T3 Code.
The rebase onto the current orchestrator v2 base, which replaces the base's interim inline worktree repair with the revival service, was done by Claude Fable 5.1 via Claude Code in T3 Code, as were the pre-review fixes that leave existing worktrees alone at turn start and take the mutation permit per worktree.

Note

Add server-side worktree lifecycle management to orchestrator v2

  • Introduces WorktreeService, WorktreeRevivalService, WorktreeLifecycle, WorktreeReaper, and WorktreeDeletionCleanup services that handle listing, pruning, reviving, and reaping worktrees on the server
  • ProviderTurnStartService now revives the thread's worktree before starting a provider turn, serializes session starts per ProviderSessionId, and closes/reopens the provider session when the worktree was revived or its generation/path changed
  • Adds three WebSocket RPCs (vcs.listWorktrees, vcs.subscribeWorktreeInventory, vcs.pruneWorktrees) with auth scopes, and a worktreeManagement capability flag so clients gate features on server support
  • Adds client UI in Source Control settings for viewing worktree inventory, configuring retention (autoPruneAfterDays default 14, deleteOrphanedImmediately default false), and pruning; useThreadActions skips legacy client-side orphan cleanup when the capability is present
  • GitWorkflowService methods (preparePullRequestThread, createWorktree, removeWorktree) now run under a WorktreeLifecycle mutation permit and signal inventory changes
  • Risk: ProviderTurnStartService no longer emits provider-session.updated and provider-thread.updated events during the initial running transition; consumers relying on those events in that phase will need to use run.updated, run-attempt.updated, or node.updated instead

Macroscope summarized bdc613b.


Note

High Risk
Touches provider turn startup, shared session close/reopen, and automatic worktree deletion; race-sensitive paths are tested but mistakes could strand runs or remove worktrees incorrectly.

Overview
Adds server-owned Git worktree lifecycle for orchestration v2: inventory from git worktree list, safe pruning rules, automatic retention/orphan cleanup, and revival of missing thread worktrees before provider turns run.

Git & workflow: New listWorkspaces / shared porcelain parsing (GitWorktree.ts), with output-size limits. GitWorkflowService routes create/remove/prepare-PR-thread work through WorktreeLifecycle (serialized mutations + inventory revision stream).

Orchestration: ProviderTurnStartService calls WorktreeRevivalService.reviveForThread, then serializes startup per ProviderSessionId via KeyedSerialExecutor. If a worktree was revived or its generation/path changed, it closes and reopens the shared provider session so cwd stays correct, with careful handling when runs are superseded mid-restart.

Background jobs: WorktreeDeletionCleanup reacts to thread.deleted events; WorktreeReaper periodically prunes inactive safe worktrees per settings. Both delegate to WorktreeService for last-moment safety checks.

Product surface: Enables worktreeManagement server capability and RPC auth for vcsListWorktrees, subscribeWorktreeInventory, and vcsPruneWorktrees. Layers wired in server.ts / startup after the effect worker starts.

Reviewed by Cursor Bugbot for commit bdc613b. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 241aad84-47f4-4428-b412-3c651f409505

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 7, 2026
Comment thread apps/server/src/vcs/WorktreeRevivalService.ts Outdated
Comment thread packages/contracts/src/worktrees.ts Outdated
Comment thread apps/server/src/vcs/GitVcsDriver.ts
Comment thread apps/server/src/vcs/WorktreeService.ts Outdated
Comment thread apps/server/src/vcs/WorktreeDeletionCleanup.ts Outdated
Comment thread apps/web/src/components/settings/SourceControlSettings.tsx
Comment thread apps/server/src/vcs/WorktreeRevivalService.ts Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the new worktree services against the Effect service conventions. Four convention issues found: two standalone *Shape service interfaces, a redundant singleton operation discriminator plus free-form message on the new worktree error classes, and a hidden optional service dependency in ProviderTurnStartService.

Posted via Macroscope — Effect Service Conventions

Comment thread packages/contracts/src/worktrees.ts Outdated
Comment thread apps/server/src/orchestration-v2/ProviderTurnStartService.ts Outdated
Comment thread apps/server/src/vcs/WorktreeRevivalService.ts Outdated
Comment thread apps/server/src/vcs/WorktreeLifecycle.ts Outdated
Comment thread apps/server/src/vcs/WorktreeService.ts Outdated
Comment thread apps/server/src/orchestration-v2/ProviderTurnStartService.ts Outdated
Comment thread apps/server/src/orchestration-v2/ProviderTurnStartService.ts Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review of the worktree management services. Prior findings on WorktreeLifecycle/WorktreeRevivalService shape interfaces, the unstructured worktree error payloads, and the Effect.serviceOption acquisition of WorktreeRevivalService all look addressed. A few smaller convention issues remain.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/vcs/WorktreeReaper.ts Outdated
Comment thread apps/server/src/vcs/WorktreeDeletionCleanup.ts Outdated
Comment thread apps/server/src/vcs/WorktreeService.ts Outdated
Comment thread apps/server/src/vcs/GitVcsDriverCore.ts Outdated
Comment thread apps/server/src/vcs/WorktreeDeletionCleanup.ts Outdated
@juliusmarminge
juliusmarminge force-pushed the t3code/codex-turn-mapping branch from 25de21d to 0af2a6e Compare August 7, 2026 12:10
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. and removed vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Aug 9, 2026
Comment thread apps/web/src/components/settings/SourceControlSettings.tsx
Comment thread apps/web/src/components/settings/SourceControlSettings.tsx
Comment thread apps/web/src/components/settings/SourceControlSettings.tsx Outdated
@StiensWout
StiensWout force-pushed the t3code/worktree-management-v2 branch from 0f4d58b to 8f7ca24 Compare August 10, 2026 09:10
Comment thread apps/server/src/vcs/WorktreeDeletionCleanup.ts
Comment thread apps/web/src/components/SidebarV2.tsx Outdated
@juliusmarminge
juliusmarminge force-pushed the t3code/codex-turn-mapping branch from 22bd872 to a27c1cc Compare August 10, 2026 17:05
@StiensWout
StiensWout force-pushed the t3code/worktree-management-v2 branch from 61184a3 to d56b638 Compare August 11, 2026 11:57
@StiensWout StiensWout changed the title [WIP] Manage worktree lifecycle on orchestrator V2 [WIP] feat(worktrees): server-managed worktree lifecycle on orchestrator v2 Aug 11, 2026
@StiensWout StiensWout changed the title [WIP] feat(worktrees): server-managed worktree lifecycle on orchestrator v2 feat(worktrees): server-managed worktree lifecycle on orchestrator v2 Aug 11, 2026
@StiensWout
StiensWout marked this pull request as ready for review August 11, 2026 12:03

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: raw git stderr is copied into a new error attribute. Everything flagged in earlier runs (service-shape interfaces, make/layer naming, the single-use mutationError helper, the parseWorktreeBranchPaths shim, structural stages on the new worktree errors, and the hidden WorktreeRevivalService requirement) is resolved in this revision.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/vcs/GitVcsDriver.ts Outdated
Comment thread apps/server/src/vcs/GitVcsDriver.ts Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the Effect service conventions in this update. Previously flagged items (inline service interfaces, plain make/layer names, structural error stages with derived messages, required WorktreeRevivalService acquisition in ProviderTurnStartService, shared worktree porcelain parser, bounded git worktree list error context) all look resolved. One remaining error-modeling nit below.

Posted via Macroscope — Effect Service Conventions

Comment thread packages/contracts/src/worktrees.ts Outdated
Comment thread apps/server/src/vcs/WorktreeService.ts Outdated
Comment thread apps/server/src/orchestration-v2/ProviderTurnStartService.ts Outdated
@macroscopeapp

macroscopeapp Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR adds server-owned worktree inventory, automatic cleanup, revival, new RPCs, and provider-session lifecycle behavior across the production server and client. It also introduces a default 14-day automatic-pruning policy, so the breadth, side effects, and changed product defaults warrant human review.

Not approved because:

  • Per-review cost limit exceeded (workspace setting). Approvability relies on correctness review in order to determine eligibility

Review your spending limits in Billing settings, or comment @macroscope-app review this PR to bypass the limit and review now. You can add or adjust custom eligibility rules. Learn more.

Comment thread apps/server/src/vcs/WorktreeService.ts Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding on the new GitVcsDriver.listWorkspaces truncation error: its context fields are hardcoded/fabricated rather than derived from the actual command and output.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/vcs/GitVcsDriver.ts Outdated
Comment thread apps/server/src/orchestration-v2/ProviderTurnStartService.ts
Comment thread apps/server/src/vcs/GitVcsDriverCore.ts Outdated
@juliusmarminge
juliusmarminge force-pushed the t3code/codex-turn-mapping branch 2 times, most recently from a186d64 to 5b1a115 Compare August 12, 2026 23:19
- Re-route steering that races completion into idempotent follow-up dispatches
- Preserve scheduled-task attribution and provider ownership history across clients
Port main's pull-request discovery, active thread ordering, async question dismissal, settlement fixes, provider-session import, attachment context, and provider correctness changes into orchestration v2.

Keep the branch's intentional composer and subagent behavior while adopting main's web and mobile fixes. Prevent headless setup terminals from hanging on the color probe, and move the v2 migration block to 050-061 after main claimed 048-049.
Restore the failed-before-start timer guard, align two server fixtures with the reconciled behavior, and remove dead files, exports, and dependencies surfaced by Knip.

Drop the temporary branch push trigger now that the PR is mergeable, so each update runs the pull-request workflow once.
Keep main's batch machine-update banner and update action while preserving the v2 runtime-based environment lock used by draft load balancing.
Adopt TypeScript 7 and Effect rc.112 across orchestration v2, including the TaggedError API migration and updated Effect-aware tests. Restore main's composer-aware scroll-to-end clearance while retaining selected-model settings sync, preview recording transfer, image galleries, desktop context menus, and layout hit targets. Regenerate the lockfile on the upgraded dependency baseline.
Advertise bounded socket snapshots and authoritative dispatch validation, omit raw command output and inline file bodies at the wire boundary, and preserve compact status metadata across web and mobile. Add transport-budget coverage for snapshots, resume, commands, legacy import, and projection maintenance.
Restore pinned-thread shelf classification, server-owned unread state, hidden-subagent-safe project ordering, guarded jump hints, draft upload cleanup, and active-provider archive guards across the current and legacy sidebars.

Bring the surrounding current-main sidebar work forward as well: canonical project favicons, stable row layout, thread file drops, account-aware mobile provider badges, and deferred desktop keyring loading.
Keep collapsed model controls in a strip, contain transition overflow, and preserve timeline spacing. Render approval requests as regular grouped worklog entries.

Implemented with GPT-6-Astra via Codex.
Adapt question attachments and Android push verification to V2 requests and shell events. Preserve composer transitions and compact worklogs while integrating upstream loading, navigation, and mobile changes. Release consumed application replay pages without retaining earlier batches.
@juliusmarminge
juliusmarminge force-pushed the t3code/codex-turn-mapping branch from 8187b17 to ada72ce Compare September 9, 2026 06:39
Rebased onto the current t3code/codex-turn-mapping base. The base's interim
inline worktree repair in ProviderTurnStartService is replaced by the
revival service this change introduces.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@StiensWout
StiensWout force-pushed the t3code/worktree-management-v2 branch from bdc613b to 8feb1e7 Compare September 9, 2026 11:27
@macroscopeapp

macroscopeapp Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Macroscope skipped reviewing this pull request. Per-review cost limit exceeded (workspace setting).

This review would cost an estimated $8.41, which exceeds your per-review limit of $8.00.

The top 3 files driving up this estimate:

File Diff Size Estimate
apps/server/src/orchestration-v2/ProviderTurnStartService.ts 38.06KB $1.90
apps/web/src/components/settings/SourceControlSettings.tsx 29.30KB $1.47
apps/server/src/vcs/WorktreeService.ts 29.23KB $1.46

Tip

To get this pull request reviewed, you can:

  1. Comment @macroscope-app on this PR to request a manual review (monthly spend limits still apply).
  2. Exclude the file(s) above from review by adding a pattern to your .macroscope/ignore.md — note that creating this file replaces Macroscope's built-in default ignores rather than extending them.
  3. Raise your cost limit in your workspace billing settings.

Turn off this reminder going forward

Revival only creates a missing directory. An existing worktree is left as
is, whatever ref it has checked out and wherever it lives, so a detached
HEAD, a switched branch, or a checkout outside the managed root no longer
fails every turn. A failed revival logs and lets the provider report the
missing directory instead of stranding the run in starting.

Only per-thread provider sessions restart after a revival; a session shared
across threads passes cwd per native thread and closing it would fail
sibling turns. Turn starts no longer take the mutation permit when the
directory exists, and the reaper holds it per worktree instead of per batch.

Also: a worktree with no linked thread is not orphaned, a project whose
directory is gone is skipped instead of failing the inventory, deletion
cleanup backoff is capped, unused exports are dropped, and the settings
search test queries the worktrees entry by title.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants